<?php
/**
 * Martin Hujer's Components
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://zfw.hujer.org/license.html
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to mhujer@gmail.com so I can send you a copy immediately.
 *
 * @category   	Mhujer
 * @package    	Mhujer_Tree
 * @author 		Martin Hujer mhujer@gmail.com
 * @license    	http://zfw.hujer.org/license.html     New BSD License
 */

/**
 * Tree Component
 * 
 * @category   	Mhujer
 * @package 	Mhujer_Tree
 * @author 		Martin Hujer mhujer@gmail.com
 * @license    	http://zfw.hujer.org/license.html     New BSD License
 * @see 		http://www.sitepoint.com/forums/showthread.php?t=215857
 * 
 */
class Mhujer_Tree
{

    /**
     * Columns mapping
     * @var array 
     */
    private $_columnMapping = null;

    /**
     * Extra columns
     * @var array
     */
    private $_extraColumns = null;

    /**
     * List of nodes
     * @var array
     */
    private $_nodes = null;

    /**
     * Sets column mapping 
     * @param array $map
     */
    public function setColumnMapping ($map = null)
    {
        if (! $this->_checkColumnMappingFormat($map)) {
            throw new InvalidArgumentException();
        }
        if ($map !== null) {
            $this->_columnMapping = $map;
        } else {
            $this->_columnMapping = array('id' => 'id', 'idp' => 'idp', 'text' => 'text');
        }
        return $this;
    }

    /**
     * Checks column mapping
     * @param array $columnMapping
     * @return boolean
     */
    private function _checkColumnMappingFormat ($columnMapping)
    {
        $m = $columnMapping;
        if (array_key_exists('id', $m) && array_key_exists('idp', $m) && array_key_exists('text', $m)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Returns columns mapping
     * @return array
     */
    public function getColumnMapping ()
    {
        return $this->_columnMapping;
    }

    /**
     * Sets extra columns mapping
     * <code>$a = array('extra1', 'extra2');</code>
     * @param array $extraColumns
     * @return boolean
     */
    public function setExtraColumns ($extraColumns)
    {
        if (is_array($extraColumns)) {
            $this->_extraColumns = $extraColumns;
            return true;
        } else {
            return false;
        }
        
    }

    /**
     * Returns extra columns mapping
     * @return array
     */
    public function getExtraColumns ()
    {
        return $this->_extraColumns;
    }

    /**
     * Checks, wheter extra columns mapping is set
     * @return boolean
     */
    public function hasExtraColumns ()
    {
        return ! is_null($this->_extraColumns);
    }

    /**
     * Loads nodes from an array like this:
     * <code>
     * $a = array();
     * $a[] = array('id' => 1, 'idp' => 0, 'text' => 'foo');
     * $a[] = array('id' => 2, 'idp' => 1, 'text' => 'bar');
     * </code>
     * @param array $nodes
     */
    public function loadNodes ($nodes)
    {
        if ($this->_columnMapping == null) {
            $this->setColumnMapping();
        }
        $all = array();
        $map = $this->_columnMapping;
        foreach ($nodes as $node) {
            $id = $node[$map['id']];
            $idp = $node[$map['idp']];
            $text = $node[$map['text']];
            if (! array_key_exists($id, $all)) {
                $all[$id] = array($map['text'] => $text, 'childs' => array());
                if ($this->hasExtraColumns()) {
                    foreach ($this->getExtraColumns() as $extra) {
                        $all[$id][$extra] = $node[$extra];
                    }
                }
            } /*else {
                $all[$id]['content'] = $text;
            }*/
            if (! array_key_exists($idp, $all)) {
                $all[$idp] = array();
            }
            $all[$idp]['childs'][$id] = &$all[$id];
        }
        $this->_nodes = $all[0];
    }

    /**
     * Return multidimensional array of list items
     * @return array
     */
    public function getNodes ()
    {
        return $this->_nodes;
    }
}
